/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/25 13:24
  *
  * @file       hd_w25qxx.h
  * @brief      Header file of Xxx hardware driver.
  *
  * @note       This file contains the Xxx object declaration.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/25     Chris        the first version
  *
  ******************************************************************************
  */


#ifndef JLC_SKY_W25QXX_H
#define JLC_SKY_W25QXX_H

#include <hd_storage.h>
#include <pd_spi.h>

struct W25QxxVtbl;

/** @defgroup Object properties
  * @{
  */
typedef struct {
    Storage super;
    SPI *spi;
    GPIO *ssel;

    // W25Qxx virtual table
    struct W25QxxVtbl *vptr;
} W25Qxx; /* extends from {@see Storage} */
/**
 * @}
 */

/** @defgroup Object virtual table definition
  * @{
  */
struct W25QxxVtbl {
    void (*init)(const W25Qxx *this);

    void (*get_id)(const W25Qxx *this, uint8_t *MID, uint16_t *DID);

    void (*read)(const W25Qxx *this, uint32_t address, uint8_t *dat, uint32_t count);

    void (*erase_sector)(const W25Qxx *this, uint32_t address);

    void (*write)(const W25Qxx *this, uint32_t address, const uint8_t *dat, uint16_t count);
};
/**
 * @}
 */

/** @defgroup Object constructor and member function declaration
  * @{
  */
void W25Qxx_constructor(W25Qxx *this, SPI *spi, GPIO *ssel);
/**
 * @}
 */

/** @defgroup Object virtual table function implementation
  * @{
  */
static inline void W25Qxx_init(const W25Qxx *this) {
    this->vptr->init(this);
}

static inline void W25Qxx_getId(const W25Qxx *this, uint8_t *MID, uint16_t *DID) {
    this->vptr->get_id(this, MID, DID);
}

static inline void W25Qxx_read(const W25Qxx *this, const uint32_t address, uint8_t *dat, const uint32_t count) {
    this->vptr->read(this, address, dat, count);
}

static inline void W25Qxx_eraseSector(const W25Qxx *this, const uint32_t address) {
    this->vptr->erase_sector(this, address);
}

static inline void W25Qxx_write(const W25Qxx *this, const uint32_t address, const uint8_t *dat, const uint16_t count) {
    this->vptr->write(this, address, dat, count);
}
/**
 * @}
 */


#define W25QXX_SECTOR_SIZE                          4096
#define W25QXX_PAGE_SIZE                            256

#define W25QXX_WRITE_ENABLE                         0x06
#define W25QXX_WRITE_DISABLE                        0x04
#define W25QXX_READ_STATUS_REGISTER_1               0x05
#define W25QXX_READ_STATUS_REGISTER_2               0x35
#define W25QXX_WRITE_STATUS_REGISTER                0x01
#define W25QXX_PAGE_PROGRAM                         0x02
#define W25QXX_QUAD_PAGE_PROGRAM                    0x32
#define W25QXX_BLOCK_ERASE_64KB                     0xD8
#define W25QXX_BLOCK_ERASE_32KB                     0x52
#define W25QXX_SECTOR_ERASE_4KB                     0x20
#define W25QXX_CHIP_ERASE                           0xC7
#define W25QXX_ERASE_SUSPEND                        0x75
#define W25QXX_ERASE_RESUME                         0x7A
#define W25QXX_POWER_DOWN                           0xB9
#define W25QXX_HIGH_PERFORMANCE_MODE                0xA3
#define W25QXX_CONTINUOUS_READ_MODE_RESET           0xFF
#define W25QXX_RELEASE_POWER_DOWN_HPM_DEVICE_ID     0xAB
#define W25QXX_MANUFACTURER_DEVICE_ID               0x90
#define W25QXX_READ_UNIQUE_ID                       0x4B
#define W25QXX_JEDEC_ID                             0x9F
#define W25QXX_READ_DATA                            0x03
#define W25QXX_FAST_READ                            0x0B
#define W25QXX_FAST_READ_DUAL_OUTPUT                0x3B
#define W25QXX_FAST_READ_DUAL_IO                    0xBB
#define W25QXX_FAST_READ_QUAD_OUTPUT                0x6B
#define W25QXX_FAST_READ_QUAD_IO                    0xEB
#define W25QXX_OCTAL_WORD_READ_QUAD_IO              0xE3
#define W25QXX_DUMMY_BYTE                           0xFF
#define W25QXX_RESET_ENABLE                         0x66
#define W25QXX_RESET_MEMORY                         0x99

#endif //JLC_SKY_W25QXX_H
